package com.acmedcare.framework.exchange.center.endpoint;

import com.acmedcare.framework.exchange.center.common.Page;
import com.acmedcare.framework.exchange.center.endpoint.exception.InvalidRequestParameterException;
import com.acmedcare.framework.exchange.center.endpoint.service.PluginService;
import com.acmedcare.framework.exchange.center.endpoint.service.TaskService;
import com.acmedcare.framework.exchange.center.entity.bean.Plugin;
import com.acmedcare.framework.exchange.center.entity.bean.PluginStatusEnum;
import com.acmedcare.framework.exchange.center.entity.bean.SchedulerType;
import com.acmedcare.framework.exchange.center.entity.bean.Task;
import com.acmedcare.framework.exchange.center.entity.dto.CommandEvent;
import com.acmedcare.framework.exchange.center.entity.dto.PluginQueryDto;
import com.acmedcare.framework.exchange.center.entity.dto.TaskActionDto;
import com.acmedcare.framework.exchange.center.entity.dto.TaskListQueryDto;
import com.acmedcare.framework.exchange.center.entity.dto.TaskListViewDto;
import com.acmedcare.framework.exchange.center.entity.dto.TaskStatusEnum;
import com.acmedcare.framework.exchange.center.repository.PluginRepository;
import com.acmedcare.framework.starter.bus.AcmedcareEventPublisher;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.net.URI;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * {@link TaskEndpoint} Defined
 *
 * @author <a href="mailto:iskp.me@gmail.com">Elve.Xu</a>
 * @version ${project.version} - 2019-09-02.
 */
@SuppressWarnings("unused")
@RestController
@Api(tags = "交换中心任务列表")
@RequestMapping("/tasks")
@Slf4j
public class TaskEndpoint {

  private final TaskService taskService;
  private final AcmedcareEventPublisher publisher;
  final PluginService pluginService;

  final PluginRepository pluginRepository;
  final PluginEndpoint pluginEndpoint;

  public TaskEndpoint(
      TaskService taskService,
      AcmedcareEventPublisher publisher,
      PluginService pluginService,
      PluginRepository repository,
      PluginEndpoint pluginEndpoint) {
    this.taskService = taskService;
    this.publisher = publisher;
    this.pluginService = pluginService;
    this.pluginRepository = repository;
    this.pluginEndpoint = pluginEndpoint;
  }

  @ApiOperation("获取任务列表")
  @GetMapping("/list")
  public ResponseEntity<Page<TaskListViewDto>> getList(TaskListQueryDto queryDto) {

    Page<TaskListViewDto> data = taskService.getList(queryDto);

    if (data == null) {

      return ResponseEntity.noContent().build();
    }

    return ResponseEntity.ok(data);
  }

  @ApiOperation("创建任务")
  @PostMapping("")
  public ResponseEntity create(@RequestBody TaskActionDto actionDto)
      throws InvalidRequestParameterException {

    validTask(actionDto);
    Long id = taskService.createTask(actionDto);
    return ResponseEntity.created(URI.create(String.format("/tasks/%s", id))).build();
  }

  @ApiOperation("更新任务")
  @PutMapping("/{taskId}")
  public ResponseEntity update(@RequestBody TaskActionDto actionDto,
      @ApiParam("任务id") @PathVariable("taskId") Long taskId)
      throws InvalidRequestParameterException {

    validTask(actionDto);
    Task task = taskService.getDetail(taskId);
    if (task == null) {

      throw new InvalidRequestParameterException("任务不存在!");
    }

    taskService.update(actionDto, taskId);
    return ResponseEntity.accepted().build();
  }

  @ApiOperation("获取任务详情")
  @GetMapping("/{taskId}")
  public ResponseEntity<Task> getDetail(@ApiParam(value = "任务id",required = true) @PathVariable("taskId") Long taskId) {

    Task task = taskService.getDetail(taskId);
    if (task == null) {

      return ResponseEntity.noContent().build();
    }

    return ResponseEntity.ok(task);
  }

  @ApiOperation("设置启停服务")
  @PostMapping("/command/{taskId}/{statusEnum}")
  public ResponseEntity command(@PathVariable("taskId") Long taskId,
      @PathVariable("statusEnum") TaskStatusEnum statusEnum)
      throws InvalidRequestParameterException, JsonProcessingException {

    Task task = taskService.getDetail(taskId);
    if (task == null) {

      return ResponseEntity.notFound().build();
    }

    CommandEvent commandEvent = new CommandEvent();
    commandEvent.setCommandType(statusEnum);
    commandEvent.setTask(task);
    String workName = "exchange-center-executor";
    if (!StringUtils.isEmpty(task.getGroupName())) {

      workName = String.format("%s-exchange-center-executor", task.getGroupName());
    }

    //如果是插件服务则将自动将插件下发到指定环境
    if (task.getSchedulerType().equals(SchedulerType.AGENT)) {

      Plugin plugin = pluginService.getByName(task.getPluginName());
      if (plugin == null) {
        throw new InvalidRequestParameterException("插件不存在，请确认后再试");
      }

      pluginEndpoint.command(plugin.getPluginId(), PluginStatusEnum.LOADED, task.getGroupName());
    }

    publisher.publishEvent(workName, commandEvent);

    return ResponseEntity.noContent().build();
  }

  private void validTask(TaskActionDto actionDto) throws InvalidRequestParameterException {

    if (StringUtils.isEmpty(actionDto.getName())) {

      throw new InvalidRequestParameterException("任务名称不允许为空!");
    }
    if (StringUtils.isEmpty(actionDto.getDescription())) {

      throw new InvalidRequestParameterException("任务描述不允许为空!");
    }
    if (actionDto.getType() == null) {

      throw new InvalidRequestParameterException("任务类型不允许为空!");
    }
    if (actionDto.getStatus() == null) {

      throw new InvalidRequestParameterException("任务状态不允许为空!");
    }
    if (StringUtils.isEmpty(actionDto.getVersion())) {

      throw new InvalidRequestParameterException("任务版本不允许为空!");
    }
    if (actionDto.getSchedulerType() == null) {

      throw new InvalidRequestParameterException("调度类型不允许为空!");
    }

    if (actionDto.getSchedulerType().equals(SchedulerType.SPARK) && !actionDto.getExecuteJar()
        .toLowerCase().startsWith("hdfs")) {

      throw new InvalidRequestParameterException("spark 模式 执行jar必须是hdfs地址!");
    }

    if (actionDto.getSchedulerType().equals(SchedulerType.AGENT)) {

      if (StringUtils.isEmpty(actionDto.getPluginName()) || StringUtils
          .isEmpty(actionDto.getAgentName())) {

        throw new InvalidRequestParameterException("插件名称或者采集器名称不允许为空！");
      }

      PluginQueryDto queryDto = new PluginQueryDto();
      queryDto.setName(actionDto.getPluginName());
      Page<?> plugins = pluginService.getList(queryDto);
      if (plugins == null || plugins.getList().isEmpty()) {

        throw new InvalidRequestParameterException("插件不存在！");
      }
    } else {

      if (StringUtils.isEmpty(actionDto.getJarName())) {

        throw new InvalidRequestParameterException("执行jar包名称不允许为空!");
      }

      if (StringUtils.isEmpty(actionDto.getExecuteJar())) {

        throw new InvalidRequestParameterException("执行jar文件不允许为空!");
      }
      if (StringUtils.isEmpty(actionDto.getExecuteMainClass())) {

        throw new InvalidRequestParameterException("执行主类不允许为空!");
      }
    }
  }
}